home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / editors / stevie36.5 < prev    next >
Internet Message Format  |  1989-05-12  |  56KB

  1. Path: xanth!indri!ames!amdcad!sun!swap!page
  2. From: page%swap@Sun.COM (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i134:  stevie - vi editor clone v3.6, Part05/06
  5. Message-ID: <104421@sun.Eng.Sun.COM>
  6. Date: 12 May 89 03:07:23 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 2069
  9. Approved: page@sun.com
  10.  
  11. Submitted-by: grwalter@watmath.waterloo.edu (Fred Walter)
  12. Posting-number: Volume 89, Issue 134
  13. Archive-name: editors/stevie36.5
  14.  
  15. # This is a shell archive.
  16. # Remove anything above and including the cut line.
  17. # Then run the rest of the file through 'sh'.
  18. # Unpacked files will be owned by you and have default permissions.
  19. #----cut here-----cut here-----cut here-----cut here----#
  20. #!/bin/sh
  21. # shar: SHell ARchive
  22. # Run the following text through 'sh' to create:
  23. #    regexp.cat.uu
  24. #    regexp.h
  25. #    regmagic.h
  26. #    regsub.c
  27. #    s_io.c
  28. #    screen.c
  29. #    search.c
  30. # This is archive 5 of a 6-part kit.
  31. # This archive created: Thu May 11 19:41:28 1989
  32. echo "extracting regexp.cat.uu"
  33. sed 's/^X//' << \SHAR_EOF > regexp.cat.uu
  34. X
  35. Xbegin 644 regexp.cat
  36. XM"@H*"E)%1T584"@S*2`@("`@("`@("`@("`@("!,:6)R87)Y($9U;F-T:6]NR
  37. XM<R`@("`@("`@("`@("`@(%)%1T584"@S*0H*"@I."$Y!"$%-"$U%"$4*("`@6
  38. XM("!R96=C;VUP+"!R96=E>&5C+"!R96=S=6(L(')E9V5R<F]R("T@<F5G=6QA1
  39. XM<B!E>'!R97-S:6]N"B`@("`@:&%N9&QE<@H*4PA360A93@A.3PA/4`A04PA3&
  40. XM20A)4PA3"B`@("`@(P@C:0AI;@AN8PAC;`AL=0AU9`AD90AE(#P(/'((<F4(Y
  41. XM96<(9V4(97@(>'`(<"X(+F@(:#X(/@H*("`@("!R"')E"&5G"&=E"&5X"'APO
  42. XM"'`@*@@J<@AR90AE9PAG8PAC;PAO;0AM<`AP*`@H90AE>`AX<`AP*0@I"B`@T
  43. XM("`@8PAC:`AH80AA<@AR("H(*F4(97@(>'`(<#L(.PH*("`@("!I"&EN"&YT.
  44. XM"'0@<@AR90AE9PAG90AE>`AX90AE8PAC*`@H<`AP<@AR;PAO9PAG+`@L(',(]
  45. XM<W0(='((<FD(:6X(;F<(9RD(*0H@("`@('((<F4(96<(9V4(97@(>'`(<"`JW
  46. XM""IP"'!R"')O"&]G"&<["#L*("`@("!C"&-H"&AA"&%R"'(@*@@J<PAS=`AT@
  47. XM<@AR:0AI;@AN9PAG.P@["@H@("`@('((<F4(96<(9W,(<W4(=6((8B@(*'`("
  48. XM<'((<F\(;V<(9RP(+"!S"'-O"&]U"'5R"')C"&-E"&4L""P@9`AD90AE<PASZ
  49. XM=`AT*0@I"B`@("`@<@AR90AE9PAG90AE>`AX<`AP("H(*G`(<'((<F\(;V<(?
  50. XM9SL(.PH@("`@(&,(8V@(:&$(87((<B`J""IS"'-O"&]U"'5R"')C"&-E"&4[T
  51. XM"#L*("`@("!C"&-H"&AA"&%R"'(@*@@J9`AD90AE<PAS=`AT.P@["@H@("`@7
  52. XM('((<F4(96<(9V4(97((<G((<F\(;W((<B@(*&T(;7,(<V<(9RD(*0H@("`@2
  53. XM(&,(8V@(:&$(87((<B`J""IM"&US"'-G"&<["#L*"D0(1$4(15,(4T,(0U((H
  54. XM4DD(25`(4%0(5$D(24\(3TX(3@H@("`@(%1H97-E(&9U;F-T:6]N<R!I;7!L6
  55. XM96UE;G0*("`@("!?"&5?"&=?"')?"&5?"'`H,2DM<W1Y;&4*("`@("!R96=U6
  56. XM;&%R(&5X<')E<W-I;VYS(&%N9"!S=7!P;W)T:6YG(&9A8VEL:71I97,N"@H@/
  57. XM("`@(%\(4E\(95\(9U\(8U\(;U\(;5\(<`H@("`@(&-O;7!I;&5S(&$@<F5G#
  58. XM=6QA<B!E>'!R97-S:6]N(&EN=&\@82!S=')U8W1U<F4@;V8@='EP90H@("`@Q
  59. XM(%\(<E\(95\(9U\(95\(>%\(<"P*("`@("!A;F0@<F5T=7)N<R!A('!O:6YT<
  60. XM97(@=&\@:70N"B`@("`@5&AE('-P86-E(&AA<R!B965N(&%L;&]C871E9"!UP
  61. XM<VEN9PH@("`@(%\(;5\(85\(;%\(;%\(;U\(8R@S*0H@("`@(&%N9"!M87D@E
  62. XM8F4@<F5L96%S960@8GD*("`@("!?"&9?"')?"&5?"&4N"@H@("`@(%\(4E\(1
  63. XM95\(9U\(95\(>%\(95\(8PH@("`@(&UA=&-H97,@82!.54PM=&5R;6EN871E)
  64. XM9"!?"'-?"'1?"')?"&E?"&Y?"&<@86=A:6YS="!T:&4@8V]M<&EL960@<F5GX
  65. XM=6QA<B!E>'!R97-S:6]N"B`@("`@:6X@7PAP7PAR7PAO7PAG+@H@("`@($ETN
  66. XM(')E='5R;G,@,2!F;W(@<W5C8V5S<R!A;F0@,"!F;W(@9F%I;'5R92P@86YD5
  67. XM(&%D:G5S=',@=&AE(&-O;G1E;G1S(&]F"B`@("`@7PAP7PAR7PAO7PAG)W,@Z
  68. XM7PAS7PAT7PAA7PAR7PAT7PAP(&%N9"!?"&5?"&Y?"&1?"'`@*'-E92!B96QO%
  69. XM=RD@86-C;W)D:6YG;'DN"@H@("`@(%1H92!M96UB97)S(&]F(&$*("`@("!?<
  70. XM"')?"&5?"&=?"&5?"'A?"'`*("`@("!S=')U8W1U<F4@:6YC;'5D92!A="!LV
  71. XM96%S="!T:&4@9F]L;&]W:6YG("AN;W0@;F5C97-S87)I;'D@:6X@;W)D97(IV
  72. XM.@H*("`@("`@("`@(&-H87(@*G-T87)T<%M.4U5"15A073L*("`@("`@("`@6
  73. XM(&-H87(@*F5N9'!;3E-50D584%T["@H@("`@('=H97)E"B`@("`@7PA.7PA3O
  74. XM7PA57PA"7PA%7PA87PA0"B`@("`@:7,@9&5F:6YE9"`H87,@,3`I(&EN('1HU
  75. XM92!H96%D97(@9FEL92X*"@H*1F]R;6%T=&5D(#@X+S$R+S,P("`@("`@("`@^
  76. XM("`@;&]C86P@("`@("`@("`@("`@("`@("`@("`@("`@("`@(#$*#`H*"@I2,
  77. XM14=%6%`H,RD@("`@("`@("`@("`@("`@3&EB<F%R>2!&=6YC=&EO;G,@("`@K
  78. XM("`@("`@("`@("!214=%6%`H,RD*"@H*("`@("!/;F-E(&$@<W5C8V5S<V9UQ
  79. XM;"!?"')?"&5?"&=?"&5?"'A?"&5?"&,@:&%S(&)E96X@9&]N92!U<VEN9R!TV
  80. XM:&4@7PAR7PAE7PAG7PAE7PAX7PAP+`H@("`@(&5A8V@@7PAS7PAT7PAA7PAR_
  81. XM7PAT7PAP+5\(95\(;E\(9%\(<"!P86ER(&1E<V-R:6)E<R!O;F4@<W5B<W1RG
  82. XM:6YG"B`@("`@=VET:&EN('1H92!?"'-?"'1?"')?"&E?"&Y?"&<L"B`@("`@3
  83. XM=VET:"!T:&4@7PAS7PAT7PAA7PAR7PAT7PAP('!O:6YT:6YG('1O('1H92!FW
  84. XM:7)S="!C:&%R86-T97(@;V8@=&AE('-U8G-T<FEN9R!A;F0*("`@("!T:&4@$
  85. XM7PAE7PAN7PAD7PAP('!O:6YT:6YG('1O('1H92!F:7)S="!C:&%R86-T97(@D
  86. XM9F]L;&]W:6YG('1H92!S=6)S=')I;F<N"B`@("`@5&AE(#!T:"!S=6)S=')I$
  87. XM;F<@:7,@=&AE('-U8G-T<FEN9R!O9B!?"'-?"'1?"')?"&E?"&Y?"&<@=&AAF
  88. XM="!M871C:&5D('1H92!W:&]L90H@("`@(')E9W5L87(@97AP<F5S<VEO;BX*.
  89. XM("`@("!4:&4@;W1H97)S(&%R92!T:&]S92!S=6)S=')I;F=S('1H870@;6%TX
  90. XM8VAE9"!P87)E;G1H97-I>F5D(&5X<')E<W-I;VYS"B`@("`@=VET:&EN('1H&
  91. XM92!R96=U;&%R(&5X<')E<W-I;VXL('=I=&@@<&%R96YT:&5S:7IE9"!E>'!RD
  92. XM97-S:6]N<R!N=6UB97)E9`H@("`@(&EN(&QE9G0M=&\M<FEG:'0@;W)D97(@Y
  93. XM;V8@=&AE:7(@;W!E;FEN9R!P87)E;G1H97-E<RX*"B`@("`@7PA27PAE7PAG8
  94. XM7PAS7PAU7PAB"B`@("`@8V]P:65S(%\(<U\(;U\(=5\(<E\(8U\(92!T;R!?)
  95. XM"&1?"&5?"'-?"'0L(&UA:VEN9R!S=6)S=&ET=71I;VYS(&%C8V]R9&EN9R!T>
  96. XM;R!T:&4*("`@("!M;W-T(')E8V5N="!?"')?"&5?"&=?"&5?"'A?"&5?"&,@2
  97. XM<&5R9F]R;65D('5S:6YG(%\(<%\(<E\(;U\(9RX*("`@("!%86-H(&EN<W1A&
  98. XM;F-E(&]F(&`F)R!I;B!?"'-?"&]?"'5?"')?"&-?"&4@:7,@<F5P;&%C960@&
  99. XM8GD@=&AE('-U8G-T<FEN9PH@("`@(&EN9&EC871E9"!B>2!?"'-?"'1?"&%?#
  100. XM"')?"'1?"'!;7P@P72!A;F0*("`@("!?"&5?"&Y?"&1?"'!;7P@P72X*("`@B
  101. XM("!%86-H(&EN<W1A;F-E(&]F(&!<7PAN)RP@=VAE<F4@7PAN(&ES(&$@9&EG@
  102. XM:70L(&ES(')E<&QA8V5D(&)Y"B`@("`@=&AE('-U8G-T<FEN9R!I;F1I8V%T(
  103. XM960@8GD*("`@("!?"'-?"'1?"&%?"')?"'1?"'!;7PAN72!A;F0*("`@("!??
  104. XM"&5?"&Y?"&1?"'!;7PAN72X*("`@("!4;R!G970@82!L:71E<F%L(&`F)R!O6
  105. XM<B!@7%\(;B<@:6YT;R!?"&1?"&5?"'-?"'0L('!R969I>"!I="!W:71H(&!<?
  106. XM)SL*("`@("!T;R!G970@82!L:71E<F%L(&!<)R!P<F5C961I;F<@8"8G(&]R_
  107. XM(&!<7PAN)RP@<')E9FEX(&ET('=I=&@*("`@("!A;F]T:&5R(&!<)RX*"B`@K
  108. XM("`@7PA27PAE7PAG7PAE7PAR7PAR7PAO7PAR"B`@("`@:7,@8V%L;&5D('=HJ
  109. XM96YE=F5R(&%N(&5R<F]R(&ES(&1E=&5C=&5D(&EN(%\(<E\(95\(9U\(8U\(7
  110. XM;U\(;5\(<"P@7PAR7PAE7PAG7PAE7PAX7PAE7PAC+`H@("`@(&]R(%\(<E\(Q
  111. XM95\(9U\(<U\(=5\(8BX*("`@("!4:&4@9&5F875L="!?"')?"&5?"&=?"&5?N
  112. XM"')?"')?"&]?"'(@=W)I=&5S('1H92!S=')I;F<@7PAM7PAS7PAG+`H@("`@J
  113. XM('=I=&@@82!S=6ET86)L92!I;F1I8V%T;W(@;V8@;W)I9VEN+`H@("`@(&]N#
  114. XM('1H92!S=&%N9&%R9`H@("`@(&5R<F]R(&]U='!U=`H@("`@(&%N9"!I;G9OP
  115. XM:V5S(%\(95\(>%\(:5\(="@R*2X*("`@("!?"%)?"&5?"&=?"&5?"')?"')?$
  116. XM"&]?"'(*("`@("!C86X@8F4@<F5P;&%C960@8GD@=&AE('5S97(@:68@;W1H(
  117. XM97(@86-T:6]N<R!A<F4@9&5S:7)A8FQE+@H*4@A210A%1PA'50A53`A,00A!]
  118. XM4@A2($4(15@(6%`(4%((4D4(15,(4U,(4TD(24\(3TX(3B!3"%-9"%E."$Y4\
  119. XM"%1!"$%8"%@*("`@("!!(')E9W5L87(@97AP<F5S<VEO;B!I<R!Z97)O(&]RH
  120. XM(&UO<F4@7PAB7PAR7PAA7PAN7PAC7PAH7PAE7PAS+"!S97!A<F%T960@8GD@1
  121. XM8'PG+@H@("`@($ET(&UA=&-H97,@86YY=&AI;F<@=&AA="!M871C:&5S(&]NR
  122. XM92!O9B!T:&4@8G)A;F-H97,N"@H@("`@($$@8G)A;F-H(&ES('IE<F\@;W(@/
  123. XM;6]R92!?"'!?"&E?"&5?"&-?"&5?"',L(&-O;F-A=&5N871E9"X*("`@("!),
  124. XM="!M871C:&5S(&$@;6%T8V@@9F]R('1H92!F:7)S="P@9F]L;&]W960@8GD@Z
  125. XM82!M871C:"!F;W(@=&AE('-E8V]N9"P@971C+@H*("`@("!!('!I96-E(&ES_
  126. XM(&%N(%\(85\(=%\(;U\(;2!P;W-S:6)L>2!F;VQL;W=E9"!B>2!@*B<L(&`K0
  127. XM)RP@;W(@8#\G+@H@("`@($%N(&%T;VT@9F]L;&]W960@8GD@8"HG(&UA=&-H'
  128. XM97,@82!S97%U96YC92!O9B`P(&]R(&UO<F4@;6%T8VAE<R!O9B!T:&4@871OJ
  129. XM;2X*("`@("!!;B!A=&]M(&9O;&QO=V5D(&)Y(&`K)R!M871C:&5S(&$@<V5Q]
  130. XM=65N8V4@;V8@,2!O<B!M;W)E(&UA=&-H97,@;V8@=&AE(&%T;VTN"B`@("`@N
  131. XM06X@871O;2!F;VQL;W=E9"!B>2!@/R<@;6%T8VAE<R!A(&UA=&-H(&]F('1H!
  132. XM92!A=&]M+"!O<B!T:&4@;G5L;"!S=')I;F<N"@H@("`@($%N(&%T;VT@:7,@4
  133. XM82!R96=U;&%R(&5X<')E<W-I;VX@:6X@<&%R96YT:&5S97,@*&UA=&-H:6YGO
  134. XM(&$@;6%T8V@@9F]R('1H90H@("`@(')E9W5L87(@97AP<F5S<VEO;BDL(&$@X
  135. XM7PAR7PAA7PAN7PAG7PAE("AS964@8F5L;W<I+"!@+B<*("`@("`H;6%T8VAI`
  136. XM;F<@86YY('-I;F=L92!C:&%R86-T97(I+"!@7B<@*&UA=&-H:6YG('1H92!N(
  137. XM=6QL('-T<FEN9R!A="!T:&4*("`@("!B96=I;FYI;F<@;V8@=&AE(&EN<'5T;
  138. XM('-T<FEN9RDL(&`D)R`H;6%T8VAI;F<@=&AE(&YU;&P@<W1R:6YG(&%T('1H.
  139. XM90H*"@I&;W)M871T960@.#@O,3(O,S`@("`@("`@("`@("!L;V-A;"`@("`@2
  140. XM("`@("`@("`@("`@("`@("`@("`@("`@,@H,"@H*"E)%1T584"@S*2`@("`@?
  141. XM("`@("`@("`@("!,:6)R87)Y($9U;F-T:6]N<R`@("`@("`@("`@("`@(%)%%
  142. XM1T584"@S*0H*"@H@("`@(&5N9"!O9B!T:&4@:6YP=70@<W1R:6YG*2P@82!@J
  143. XM7"<@9F]L;&]W960@8GD@82!S:6YG;&4@8VAA<F%C=&5R("AM871C:&EN9PH@G
  144. XM("`@('1H870@8VAA<F%C=&5R*2P@;W(@82!S:6YG;&4@8VAA<F%C=&5R('=I$
  145. XM=&@@;F\@;W1H97(@<VEG;FEF:6-A;F-E"B`@("`@*&UA=&-H:6YG('1H870@L
  146. XM8VAA<F%C=&5R*2X*"B`@("`@02!?"')?"&%?"&Y?"&=?"&4@:7,@82!S97%U$
  147. XM96YC92!O9B!C:&%R86-T97)S(&5N8VQO<V5D(&EN(&!;72<N"B`@("`@270@(
  148. XM;F]R;6%L;'D@;6%T8VAE<R!A;GD@<VEN9VQE(&-H87)A8W1E<B!F<F]M('1H:
  149. XM92!S97%U96YC92X*("`@("!)9B!T:&4@<V5Q=65N8V4@8F5G:6YS('=I=&@@3
  150. XM8%XG+`H@("`@(&ET(&UA=&-H97,@86YY('-I;F=L92!C:&%R86-T97(@7PANI
  151. XM7PAO7PAT(&9R;VT@=&AE(')E<W0@;V8@=&AE('-E<75E;F-E+@H@("`@($EF:
  152. XM('1W;R!C:&%R86-T97)S(&EN('1H92!S97%U96YC92!A<F4@<V5P87)A=&5D\
  153. XM(&)Y(&`M)RP@=&AI<R!I<R!S:&]R=&AA;F0*("`@("!F;W(@=&AE(&9U;&P@_
  154. XM;&ES="!O9B!!4T-)22!C:&%R86-T97)S(&)E='=E96X@=&AE;0H@("`@("AE)
  155. XM+F<N(&!;,"TY72<@;6%T8VAE<R!A;GD@9&5C:6UA;"!D:6=I="DN"B`@("`@&
  156. XM5&\@:6YC;'5D92!A(&QI=&5R86P@8%TG(&EN('1H92!S97%U96YC92P@;6%KO
  157. XM92!I="!T:&4@9FER<W0@8VAA<F%C=&5R"B`@("`@*&9O;&QO=VEN9R!A('!O[
  158. XM<W-I8FQE(&!>)RDN"B`@("`@5&\@:6YC;'5D92!A(&QI=&5R86P@8"TG+"!MJ
  159. XM86ME(&ET('1H92!F:7)S="!O<B!L87-T(&-H87)A8W1E<BX*"D$(04T(34((Q
  160. XM0DD(24<(1U4(54D(250(5%D(60H@("`@($EF(&$@<F5G=6QA<B!E>'!R97-S^
  161. XM:6]N(&-O=6QD(&UA=&-H('1W;R!D:69F97)E;G0@<&%R=',@;V8@=&AE(&EN2
  162. XM<'5T('-T<FEN9RP*("`@("!I="!W:6QL(&UA=&-H('1H92!O;F4@=VAI8V@@>
  163. XM8F5G:6YS(&5A<FQI97-T+@H@("`@($EF(&)O=&@@8F5G:6X@:6X@=&AE('-AV
  164. XM;64@<&QA8V4@("`@8G5T(&UA=&-H(&1I9F9E<F5N="!L96YG=&AS+"!O<B!M5
  165. XM871C:`H@("`@('1H92!S86UE(&QE;F=T:"!I;B!D:69F97)E;G0@=V%Y<RP@Q
  166. XM;&EF92!G971S(&UE<W-I97(L(&%S(&9O;&QO=W,N"@H@("`@($EN(&=E;F5R;
  167. XM86PL('1H92!P;W-S:6)I;&ET:65S(&EN(&$@;&ES="!O9B!B<F%N8VAE<R!AM
  168. XM<F4@8V]N<VED97)E9"!I;@H@("`@(&QE9G0M=&\M<FEG:'0@;W)D97(L('1HB
  169. XM92!P;W-S:6)I;&ET:65S(&9O<B!@*B<L(&`K)RP@86YD(&`_)R!A<F4*("`@E
  170. XM("!C;VYS:61E<F5D(&QO;F=E<W0M9FER<W0L(&YE<W1E9"!C;VYS=')U8W1S8
  171. XM(&%R92!C;VYS:61E<F5D(&9R;VT@=&AE"B`@("`@;W5T97)M;W-T(&EN+"!A-
  172. XM;F0@8V]N8V%T96YA=&5D(&-O;G-T<G5C=',@87)E(&-O;G-I9&5R960@;&5F"
  173. XM=&UO<W0M9FER<W0N"B`@("`@5&AE(&UA=&-H('1H870@=VEL;"!B92!C:&]S/
  174. XM96X@:7,@=&AE(&]N92!T:&%T('5S97,@=&AE(&5A<FQI97-T"B`@("`@<&]S9
  175. XM<VEB:6QI='D@:6X@=&AE(&9I<G-T(&-H;VEC92!T:&%T(&AA<R!T;R!B92!MX
  176. XM861E+@H@("`@($EF('1H97)E(&ES(&UO<F4@=&AA;B!O;F4@8VAO:6-E+"!TP
  177. XM:&4@;F5X="!W:6QL(&)E(&UA9&4@:6X@=&AE('-A;64@;6%N;F5R"B`@("`@+
  178. XM*&5A<FQI97-T('!O<W-I8FEL:71Y*2!S=6)J96-T('1O('1H92!D96-I<VEOY
  179. XM;B!O;B!T:&4@9FER<W0@8VAO:6-E+@H@("`@($%N9"!S;R!F;W)T:"X*"B`@1
  180. XM("`@1F]R(&5X86UP;&4L(&`H86)\82EB*F,G(&-O=6QD(&UA=&-H(&!A8F,GW
  181. XM(&EN(&]N92!O9B!T=V\@=V%Y<RX*("`@("!4:&4@9FER<W0@8VAO:6-E(&EST
  182. XM(&)E='=E96X@8&%B)R!A;F0@8&$G.R!S:6YC92!@86(G(&ES(&5A<FQI97(L2
  183. XM(&%N9"!D;V5S"B`@("`@;&5A9"!T;R!A('-U8V-E<W-F=6P@;W9E<F%L;"!MD
  184. XM871C:"P@:70@:7,@8VAO<V5N+@H@("`@(%-I;F-E('1H92!@8B<@:7,@86QRT
  185. XM96%D>2!S<&]K96X@9F]R+`H@("`@('1H92!@8BHG(&UU<W0@;6%T8V@@:71S*
  186. XM(&QA<W0@<&]S<VEB:6QI='DM+71H92!E;7!T>2!S=')I;F<M+7-I;F-E"B`@&
  187. XM("`@:70@;75S="!R97-P96-T('1H92!E87)L:65R(&-H;VEC92X*"B`@("`@.
  188. XM26X@=&AE('!A<G1I8W5L87(@8V%S92!W:&5R92!N;R!@?"=S(&%R92!P<F5SK
  189. XM96YT(&%N9"!T:&5R92!I<R!O;FQY(&]N90H@("`@(&`J)RP@8"LG+"!O<B!@8
  190. XM/R<L('1H92!N970@969F96-T(&ES('1H870@=&AE(&QO;F=E<W0@<&]S<VEBA
  191. XM;&4*("`@("!M871C:"!W:6QL(&)E(&-H;W-E;BX*("`@("!3;R!@86(J)RP@A
  192. XM<')E<V5N=&5D('=I=&@@8'AA8F)B8GDG+"!W:6QL(&UA=&-H(&!A8F)B8B<N6
  193. XM"B`@("`@3F]T92!T:&%T(&EF(&!A8BHG(&ES('1R:65D(&%G86EN<W0@8'AAH
  194. XM8GEA8F)B>B<L(&ET"B`@("`@=VEL;"!M871C:"!@86(G(&IU<W0@869T97(@=
  195. XM8'@G+"!D=64@=&\@=&AE(&)E9VEN<RUE87)L:65S="!R=6QE+@H@("`@("A)L
  196. XM;B!E9F9E8W0L('1H92!D96-I<VEO;B!O;B!W:&5R92!T;R!S=&%R="!T:&4@`
  197. XM;6%T8V@@:7,@=&AE(&9I<G-T(&-H;VEC90H@("`@('1O(&)E(&UA9&4L(&AE!
  198. XM;F-E('-U8G-E<75E;G0@8VAO:6-E<R!M=7-T(')E<W!E8W0@:70@979E;B!IV
  199. XM9B!T:&ES(&QE861S('1H96T*("`@("!T;R!L97-S+7!R969E<G)E9"!A;'1E+
  200. XM<FYA=&EV97,N*0H*4PA310A%10A%($$(04P(3%,(4T\(3PH@("`@(&5G<F5P$
  201. XM*#$I+"!E>'!R*#$I"@H*"@H*1F]R;6%T=&5D(#@X+S$R+S,P("`@("`@("`@%
  202. XM("`@;&]C86P@("`@("`@("`@("`@("`@("`@("`@("`@("`@(#,*#`H*"@I2.
  203. XM14=%6%`H,RD@("`@("`@("`@("`@("`@3&EB<F%R>2!&=6YC=&EO;G,@("`@K
  204. XM("`@("`@("`@("!214=%6%`H,RD*"@H*1`A$20A)00A!1PA'3@A.3PA/4PA39
  205. XM5`A420A)0PA#4PA3"B`@("`@7PA27PAE7PAG7PAC7PAO7PAM7PAP(')E='5R@
  206. XM;G,@3E5,3"!F;W(@82!F86EL=7)E"B`@("`@*%\(<E\(95\(9U\(95\(<E\(]
  207. XM<E\(;U\(<B!P97)M:71T:6YG*2P*("`@("!W:&5R92!F86EL=7)E<R!A<F4@1
  208. XM<WEN=&%X(&5R<F]R<RP@97AC965D:6YG(&EM<&QE;65N=&%T:6]N(&QI;6ETA
  209. XM<RP*("`@("!O<B!A<'!L>6EN9R!@*R<@;W(@8"HG('1O(&$@<&]S<VEB;'DM8
  210. XM;G5L;"!O<&5R86YD+@H*2`A(20A)4PA35`A43PA/4@A260A9"B`@("`@0F]TQ
  211. XM:"!C;V1E(&%N9"!M86YU86P@<&%G92!W97)E"B`@("`@=W)I='1E;B!A="!5%
  212. XM(&]F(%0N"B`@("`@5&AE>2!A<F4@:6YT96YD960@=&\@8F4@8V]M<&%T:6)LC
  213. XM92!W:71H('1H92!"96QL(%8X(%\(<E\(95\(9U\(95\(>%\(<"@S*2P*("`@>
  214. XM("!B=70@87)E(&YO="!D97)I=F5D(&9R;VT@0F5L;"!C;V1E+@H*0@A"50A5%
  215. XM1PA'4PA3"B`@("`@16UP='D@8G)A;F-H97,@86YD(&5M<'1Y(')E9W5L87(@W
  216. XM97AP<F5S<VEO;G,@87)E(&YO="!P;W)T86)L92!T;R!6."X*"B`@("`@5&AEY
  217. XM(')E<W1R:6-T:6]N(&%G86EN<W0*("`@("!A<'!L>6EN9R!@*B<@;W(@8"LG/
  218. XM('1O(&$@<&]S<VEB;'DM;G5L;"!O<&5R86YD(&ES(&%N(&%R=&EF86-T(&]F8
  219. XM('1H90H@("`@('-I;7!L:7-T:6,@:6UP;&5M96YT871I;VXN"@H@("`@($1OG
  220. XM97,@;F]T('-U<'!O<G0@7PAE7PAG7PAR7PAE7PAP)W,@;F5W;&EN92US97!A^
  221. XM<F%T960@8G)A;F-H97,["B`@("`@;F5I=&AE<B!D;V5S('1H92!6."!?"')?\
  222. XM"&5?"&=?"&5?"'A?"'`H,RDL('1H;W5G:"X*"B`@("`@1'5E('1O(&5M<&AA*
  223. XM<VES(&]N"B`@("`@8V]M<&%C=&YE<W,@86YD('-I;7!L:6-I='DL"B`@("`@F
  224. XM:70G<R!N;W0@<W1R:6MI;F=L>2!F87-T+@H@("`@($ET(&1O97,@9VEV92!SD
  225. XM<&5C:6%L(&%T=&5N=&EO;B!T;R!H86YD;&EN9R!S:6UP;&4@8V%S97,@<75I4
  226. XM8VML>2X*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@I&;W)M871T960@3
  227. XM.#@O,3(O,S`@("`@("`@("`@("!L;V-A;"`@("`@("`@("`@("`@("`@("`@?
  228. X+("`@("`@("`@-`H@^
  229. X``
  230. Xend
  231. Xsize 8651
  232. SHAR_EOF
  233. echo "extracting regexp.h"
  234. sed 's/^X//' << \SHAR_EOF > regexp.h
  235. X/*
  236. X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  237. X *
  238. X * This is NOT the original regular expression code as written by
  239. X * Henry Spencer. This code has been modified specifically for use
  240. X * with the STEVIE editor, and should not be used apart from compiling
  241. X * STEVIE. If you want a good regular expression library, get the
  242. X * original code. The copyright notice that follows is from the
  243. X * original.
  244. X *
  245. X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  246. X *
  247. X * Definitions etc. for regexp(3) routines.
  248. X *
  249. X * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
  250. X * not the System V one.
  251. X */
  252. X#define NSUBEXP  10
  253. Xtypedef struct regexp {
  254. X    char           *startp[NSUBEXP];
  255. X    char           *endp[NSUBEXP];
  256. X    char            regstart;    /* Internal use only. */
  257. X    char            reganch;    /* Internal use only. */
  258. X    char           *regmust;    /* Internal use only. */
  259. X    int             regmlen;    /* Internal use only. */
  260. X    char            program[1];    /* Unwarranted chumminess with compiler. */
  261. X}               regexp;
  262. X
  263. Xextern regexp  *regcomp();
  264. Xextern int      regexec();
  265. Xextern void     regsub();
  266. Xextern void     regerror();
  267. X
  268. X#ifndef    ORIGINAL
  269. Xextern int      reg_ic;        /* set non-zero to ignore case in searches */
  270. X#endif
  271. SHAR_EOF
  272. echo "extracting regmagic.h"
  273. sed 's/^X//' << \SHAR_EOF > regmagic.h
  274. X/*
  275. X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  276. X *
  277. X * This is NOT the original regular expression code as written by
  278. X * Henry Spencer. This code has been modified specifically for use
  279. X * with the STEVIE editor, and should not be used apart from compiling
  280. X * STEVIE. If you want a good regular expression library, get the
  281. X * original code. The copyright notice that follows is from the
  282. X * original.
  283. X *
  284. X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  285. X *
  286. X * The first byte of the regexp internal "program" is actually this magic
  287. X * number; the start node begins in the second byte.
  288. X */
  289. X#define    MAGIC    0234
  290. SHAR_EOF
  291. echo "extracting regsub.c"
  292. sed 's/^X//' << \SHAR_EOF > regsub.c
  293. X/*
  294. X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  295. X *
  296. X * This is NOT the original regular expression code as written by
  297. X * Henry Spencer. This code has been modified specifically for use
  298. X * with the STEVIE editor, and should not be used apart from compiling
  299. X * STEVIE. If you want a good regular expression library, get the
  300. X * original code. The copyright notice that follows is from the
  301. X * original.
  302. X *
  303. X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  304. X *
  305. X * regsub
  306. X *
  307. X *      Copyright (c) 1986 by University of Toronto.
  308. X *      Written by Henry Spencer.  Not derived from licensed software.
  309. X *
  310. X *      Permission is granted to anyone to use this software for any
  311. X *      purpose on any computer system, and to redistribute it freely,
  312. X *      subject to the following restrictions:
  313. X *
  314. X *      1. The author is not responsible for the consequences of use of
  315. X *              this software, no matter how awful, even if they arise
  316. X *              from defects in it.
  317. X *
  318. X *      2. The origin of this software must not be misrepresented, either
  319. X *              by explicit claim or by omission.
  320. X *
  321. X *      3. Altered versions must be plainly marked as such, and must not
  322. X *              be misrepresented as being the original software.
  323. X *
  324. X * $Log:        regsub.c,v $
  325. X * Revision 1.2  88/04/28  08:11:25  tony
  326. X * First modification of the regexp library. Added an external variable
  327. X * 'reg_ic' which can be set to indicate that case should be ignored.
  328. X * Added a new parameter to regexec() to indicate that the given string
  329. X * comes from the beginning of a line and is thus eligible to match
  330. X * 'beginning-of-line'.
  331. X * 
  332. X */
  333. X
  334. X#include "env.h"
  335. X
  336. X#ifdef  MEGAMAX
  337. Xoverlay "regexp"
  338. X#endif
  339. X
  340. X#include <stdio.h>
  341. X#include "regexp.h"
  342. X#include "regmagic.h"
  343. X
  344. X#ifndef CHARBITS
  345. X#define UCHARAT(p)      ((int)*(unsigned char *)(p))
  346. X#else
  347. X#define UCHARAT(p)      ((int)*(p)&CHARBITS)
  348. X#endif
  349. X
  350. X/*
  351. X - regsub - perform substitutions after a regexp match
  352. X */
  353. Xvoid
  354. Xregsub(prog, source, dest)
  355. X    regexp         *prog;
  356. X    char           *source;
  357. X    char           *dest;
  358. X{
  359. X    register char  *src;
  360. X    register char  *dst;
  361. X    register char   c;
  362. X    register int    no;
  363. X    register int    len;
  364. X    extern char    *strncpy();
  365. X
  366. X    if (prog == NULL || source == NULL || dest == NULL) {
  367. X    regerror("NULL parm to regsub");
  368. X    return;
  369. X    }
  370. X    if (UCHARAT(prog->program) != MAGIC) {
  371. X    regerror("damaged regexp fed to regsub");
  372. X    return;
  373. X    }
  374. X    src = source;
  375. X    dst = dest;
  376. X    while ((c = *src++) != '\0') {
  377. X    if (c == '&')
  378. X        no = 0;
  379. X    else if (c == '\\' && '0' <= *src && *src <= '9')
  380. X        no = *src++ - '0';
  381. X    else
  382. X        no = -1;
  383. X    if (no < 0) {        /* Ordinary character. */
  384. X        if (c == '\\' && (*src == '\\' || *src == '&'))
  385. X        c = *src++;
  386. X        *dst++ = c;
  387. X    } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
  388. X        len = prog->endp[no] - prog->startp[no];
  389. X        (void) strncpy(dst, prog->startp[no], len);
  390. X        dst += len;
  391. X        if (len != 0 && *(dst - 1) == '\0') {    /* strncpy hit NUL. */
  392. X        regerror("damaged match string");
  393. X        return;
  394. X        }
  395. X    }
  396. X    }
  397. X    *dst = '\0';
  398. X}
  399. SHAR_EOF
  400. echo "extracting s_io.c"
  401. sed 's/^X//' << \SHAR_EOF > s_io.c
  402. X/*
  403. X * s_io() - routines that do screen I/O or effect what we think is
  404. X *          on the screen.
  405. X *
  406. X * By G. R. (Fred) Walter    watmath!watcgl!grwalter 
  407. X */
  408. X
  409. X#include "stevie.h"
  410. X
  411. X/*
  412. X * screen_ins(row, nlines, total_rows) - insert 'nlines' lines at 'row' 
  413. X *
  414. X * NOTE: this routine assumes it is called with valid arguments.
  415. X */
  416. X
  417. Xstatic void
  418. Xscreen_ins(row, nlines, total_rows)
  419. X    int             row;
  420. X    int             nlines;
  421. X    int             total_rows;
  422. X{
  423. X    if (nlines < 1 || (row + nlines) > total_rows)
  424. X    return;
  425. X
  426. X#ifndef T_IL_B
  427. X    {
  428. X    int             i;
  429. X
  430. X    for (i = 0; i < nlines; i++) {
  431. X        windgoto(row, 0);
  432. X        outstr(T_IL);
  433. X    }
  434. X    }
  435. X#else
  436. X    windgoto(row, 0);
  437. X    outstr(T_IL);
  438. X    if (nlines >= 10)
  439. X    outchar((char) (nlines / 10 + '0'));
  440. X    outchar((char) (nlines % 10 + '0'));
  441. X    outstr(T_IL_B);
  442. X#endif
  443. X
  444. X    /* delete any garbage that may have been shifted to the status line */
  445. X    windgoto(total_rows - 1, 0);
  446. X    outstr(T_EL);
  447. X}
  448. X
  449. X/*
  450. X * screen_del(row, nlines, total_rows) - delete 'nlines' lines at 'row' 
  451. X *
  452. X * NOTE: this routine assumes it is called with valid arguments.
  453. X */
  454. X
  455. Xstatic void
  456. Xscreen_del(row, nlines, total_rows)
  457. X    int             row;
  458. X    int             nlines;
  459. X    int             total_rows;
  460. X{
  461. X    if (nlines < 1 || (row + nlines) > total_rows)
  462. X    return;
  463. X
  464. X    /* delete any garbage that may have been on the status line */
  465. X    windgoto(total_rows - 1, 0);
  466. X    outstr(T_EL);
  467. X
  468. X#ifndef T_DL_B
  469. X    {
  470. X    int             i;
  471. X
  472. X    for (i = 0; i < nlines; i++) {
  473. X        windgoto(row, 0);
  474. X        outstr(T_DL);    /* delete a line */
  475. X    }
  476. X    }
  477. X#else
  478. X    windgoto(row, 0);
  479. X    outstr(T_DL);
  480. X    if (nlines >= 10)
  481. X    outchar((char) (nlines / 10 + '0'));
  482. X    outchar((char) (nlines % 10 + '0'));
  483. X    outstr(T_DL_B);
  484. X#endif
  485. X}
  486. X
  487. X/*
  488. X * screen_refresh()
  489. X *
  490. X * Based on the current value of Topchar, refresh the contents of the screen
  491. X * and update Botchar.
  492. X */
  493. X
  494. Xstatic void
  495. Xscreen_refresh(type)
  496. X    int             type;
  497. X{
  498. X    char           *ptr;
  499. X    int             total_rows;
  500. X    int             row;
  501. X    int             col;
  502. X    LINE           *memp;
  503. X    LPtr            start;
  504. X    bool_t          off_top;
  505. X    bool_t          done;    /* if TRUE, we hit the end of the file */
  506. X    bool_t          didline;    /* if TRUE, we finished the last line */
  507. X    int             lno;    /* number of the line we're doing */
  508. X    int             coff;
  509. X    int             idx;
  510. X    int             i;
  511. X    int             j;
  512. X
  513. X    if (NumLineSizes <= 0)
  514. X    type = NOT_VALID;
  515. X
  516. X    if (!RedrawingDisabled)
  517. X    outstr(T_CI);
  518. X
  519. X    off_top = FALSE;
  520. X    idx = 0;
  521. X    row = 0;
  522. X    total_rows = Rows - 1;
  523. X    memp = Topchar->linep;
  524. X
  525. X    if ((type == VALID) || (type == VALID_TO_CURSCHAR)) {
  526. X    j = -1;
  527. X    for (i = 0; i < NumLineSizes; i++) {
  528. X        if (LinePointers[i] == memp) {
  529. X        j = i;
  530. X        break;
  531. X        }
  532. X        row += LineSizes[i];
  533. X    }
  534. X    if (j == -1) {
  535. X        /* Are we off the top of the screen by one line ? */
  536. X        if (memp->next == LinePointers[0]) {
  537. X        i = plines(Topchar->linep->s);
  538. X        if (i < (total_rows)) {
  539. X            off_top = TRUE;
  540. X            for (idx = NumLineSizes; idx > 0; idx--) {
  541. X            LinePointers[idx] = LinePointers[idx - 1];
  542. X            LineSizes[idx] = LineSizes[idx - 1];
  543. X            }
  544. X            LineSizes[idx] = (char) i;
  545. X            if (!RedrawingDisabled)
  546. X            screen_ins(0, i, Rows);
  547. X        }
  548. X        }
  549. X        row = 0;
  550. X    } else if (j == 0 && type == VALID) {
  551. X        if (!RedrawingDisabled)
  552. X        outstr(T_CV);
  553. X        return;
  554. X    } else {
  555. X        if (!RedrawingDisabled)
  556. X        screen_del(0, row, Rows);
  557. X        row = 0;
  558. X        for (;;) {
  559. X        LineSizes[idx] = LineSizes[j];
  560. X        LinePointers[idx] = LinePointers[j];
  561. X
  562. X        if (type == VALID_TO_CURSCHAR) {
  563. X            if (LinePointers[idx] == Curschar->linep) {
  564. X            memp = LinePointers[idx];
  565. X            break;
  566. X            }
  567. X        }
  568. X        j++;
  569. X        if (j >= NumLineSizes) {
  570. X            memp = LinePointers[idx];
  571. X            if (memp->next != Fileend->linep) {
  572. X            row += LineSizes[idx];
  573. X            idx++;
  574. X            memp = memp->next;
  575. X            }
  576. X            break;
  577. X        }
  578. X        row += LineSizes[idx];
  579. X        idx++;
  580. X        }
  581. X    }
  582. X    }
  583. X    coff = 0;
  584. X    if (P(P_NU)) {
  585. X    coff = 8;
  586. X    start.linep = memp;
  587. X    lno = cntllines(Filemem, &start);
  588. X    }
  589. X    didline = TRUE;
  590. X    done = FALSE;
  591. X
  592. X    for (;;) {
  593. X    ptr = format_line(memp->s, &col);
  594. X    i = 1 + ((col - 1) / Columns);
  595. X    if ((row + i) <= total_rows) {
  596. X        LinePointers[idx] = memp;
  597. X        LineSizes[idx++] = (char) i;
  598. X        if (!RedrawingDisabled) {
  599. X        windgoto(row, 0);
  600. X
  601. X        if (P(P_NU))
  602. X            outstr(mkline(lno++));
  603. X        outstr(ptr);
  604. X
  605. X        j = col + coff;
  606. X        col = j % Columns;
  607. X        if ((col != 0) || (j == 0)) {
  608. X#ifdef T_END_L
  609. X            windgoto(row + i - 1, col);
  610. X            outstr(T_END_L);
  611. X#else
  612. X            for (; col < Columns; col++)
  613. X            outchar(' ');
  614. X#endif
  615. X        }
  616. X        }
  617. X        row += i;
  618. X        if (memp->next != Fileend->linep) {
  619. X        memp = memp->next;
  620. X        } else {
  621. X        done = TRUE;
  622. X        break;
  623. X        }
  624. X        if (off_top)
  625. X        break;
  626. X    } else {
  627. X        didline = FALSE;
  628. X        break;
  629. X    }
  630. X    }
  631. X
  632. X    /* Do we have to do off the top of the screen processing ? */
  633. X    if (off_top && !done) {
  634. X    row = 0;
  635. X    for (idx = 0; idx <= NumLineSizes && row < total_rows; idx++) {
  636. X        row += LineSizes[idx];
  637. X    }
  638. X
  639. X    idx--;
  640. X
  641. X    if (row < total_rows) {
  642. X        done = TRUE;
  643. X        idx++;
  644. X    } else if (row > total_rows) {
  645. X        row -= LineSizes[idx];
  646. X        didline = FALSE;
  647. X        memp = LinePointers[idx];
  648. X    } else {
  649. X        didline = TRUE;
  650. X        memp = LinePointers[idx]->next;
  651. X        idx++;
  652. X    }
  653. X    }
  654. X    NumLineSizes = idx;
  655. X
  656. X    /*
  657. X     * If we didn't hit the end of the file, and we didn't finish the last
  658. X     * line we were working on, then the line didn't fit. 
  659. X     */
  660. X    if (!done && !didline) {
  661. X    if (!RedrawingDisabled) {
  662. X        /* Clear the rest of the screen. */
  663. X#ifdef T_END_D
  664. X        windgoto(row, 0);
  665. X        outstr(T_END_D);
  666. X#else
  667. X        screen_del(row, total_rows - row, Rows);
  668. X        windgoto(row, 0);
  669. X#endif
  670. X        /* put '@'s on rows that are part of a line that's too long */
  671. X        for (; row < total_rows; row++)
  672. X        outstr("@\n\r");
  673. X    }
  674. X    Botchar->linep = memp;
  675. X    } else {
  676. X    if (!RedrawingDisabled && !off_top) {
  677. X        /* Clear the rest of the screen. */
  678. X#ifdef T_END_D
  679. X        windgoto(row, 0);
  680. X        outstr(T_END_D);
  681. X#else
  682. X        screen_del(row, total_rows - row, Rows);
  683. X        windgoto(row, 0);
  684. X#endif
  685. X        /* put '~'s on rows that aren't part of the file. */
  686. X        for (; row < total_rows; row++)
  687. X        outstr("~\n\r");
  688. X    }
  689. X    if (done)        /* we hit the end of the file */
  690. X        *Botchar = *Fileend;
  691. X    else
  692. X        Botchar->linep = memp;    /* FIX - prev? */
  693. X    }
  694. X
  695. X    if (!RedrawingDisabled)
  696. X    outstr(T_CV);
  697. X}
  698. X
  699. X/*
  700. X * s_refresh()
  701. X *
  702. X * Based on the current value of Curschar, (if necessary) update Topchar and
  703. X * Botchar and refresh the screen contensts.
  704. X */
  705. X
  706. Xvoid
  707. Xs_refresh(type)
  708. X    int             type;
  709. X{
  710. X    LPtr           *p;
  711. X    LPtr           *pp;
  712. X    int             i;
  713. X    int             nlines;
  714. X    int             refreshed;
  715. X
  716. X    refreshed = FALSE;
  717. X
  718. X    if (bufempty()) {        /* special case - file is empty */
  719. X    *Topchar = *Filemem;
  720. X    *Curschar = *Filemem;
  721. X    screen_refresh(NOT_VALID);
  722. X    return;
  723. X    }
  724. X    if (NumLineSizes < 0) {
  725. X    type = NOT_VALID;
  726. X    }
  727. X    if (type != VALID) {
  728. X    screen_refresh(type);
  729. X    refreshed = TRUE;
  730. X    type = VALID;
  731. X    }
  732. X    if (LINEOF(Curschar) < LINEOF(Topchar)) {
  733. X    nlines = cntllines(Curschar, Topchar);
  734. X    /*
  735. X     * if the cursor is above the top of the screen, put it at the top of
  736. X     * the screen.. 
  737. X     */
  738. X    *Topchar = *Curschar;
  739. X    Topchar->index = 0;
  740. X    /*
  741. X     * ... and, if we weren't very close to begin with, we scroll so that
  742. X     * the line is close to the middle. 
  743. X     */
  744. X    if (nlines > Rows / 3) {
  745. X        p = Topchar;
  746. X        for (i = 0; i < Rows / 3; i += plines(p->linep->s)) {
  747. X        pp = prevline(p);
  748. X        if (pp == NULL)
  749. X            break;
  750. X        p = pp;
  751. X        }
  752. X        *Topchar = *p;
  753. X    }
  754. X    screen_refresh(VALID);
  755. X    } else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
  756. X    nlines = cntllines(Botchar, Curschar);
  757. X    /*
  758. X     * If the cursor is off the bottom of the screen, put it at the top
  759. X     * of the screen.. ... and back up 
  760. X     */
  761. X    if (nlines > Rows / 3) {
  762. X        p = Curschar;
  763. X        for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) {
  764. X        pp = prevline(p);
  765. X        if (pp == NULL)
  766. X            break;
  767. X        p = pp;
  768. X        }
  769. X        *Topchar = *p;
  770. X    } else {
  771. X        scrollup(nlines);
  772. X    }
  773. X    screen_refresh(VALID);
  774. X    } else if (refreshed == FALSE) {
  775. X    screen_refresh(type);
  776. X    }
  777. X    /* Check if we are below Botchar (this can occur). */
  778. X    if (LINEOF(Curschar) == LINEOF(Botchar)) {
  779. X    pp = nextline(Topchar);
  780. X    if (pp != NULL) {
  781. X        Topchar->linep = pp->linep;
  782. X        screen_refresh(VALID);
  783. X    }
  784. X    } else if (LINEOF(Curschar) > LINEOF(Botchar)) {
  785. X    nlines = cntllines(Botchar, Curschar);
  786. X    /*
  787. X     * If the cursor is off the bottom of the screen, put it at the top
  788. X     * of the screen.. ... and back up 
  789. X     */
  790. X    if (nlines > Rows / 3) {
  791. X        p = Curschar;
  792. X        for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) {
  793. X        pp = prevline(p);
  794. X        if (pp == NULL)
  795. X            break;
  796. X        p = pp;
  797. X        }
  798. X        *Topchar = *p;
  799. X    } else {
  800. X        scrollup(nlines);
  801. X    }
  802. X    screen_refresh(VALID);
  803. X    }
  804. X}
  805. X
  806. X/*
  807. X * s_clear() - clear the screen and mark the stored information as invalid.
  808. X */
  809. Xvoid
  810. Xs_clear()
  811. X{
  812. X    outstr(T_ED);        /* clear the display */
  813. X    S_NOT_VALID;
  814. X}
  815. X
  816. X/*
  817. X * Update_Botchar()
  818. X *
  819. X * Based on the current value of Topchar update Botchar.
  820. X */
  821. X
  822. Xvoid
  823. XUpdate_Botchar()
  824. X{
  825. X    int             row;
  826. X    LINE           *memp;
  827. X    int             total_rows;
  828. X    int             i;
  829. X
  830. X    row = 0;
  831. X    total_rows = Rows - 1;
  832. X    memp = Topchar->linep;
  833. X
  834. X    for (;;) {
  835. X    i = plines(memp->s);
  836. X    if ((row + i) <= total_rows) {
  837. X        row += i;
  838. X        memp = memp->next;
  839. X        if (memp == Fileend->linep)
  840. X        break;
  841. X    } else {
  842. X        break;
  843. X    }
  844. X    }
  845. X    Botchar->linep = memp;
  846. X
  847. X    MustUpdateBotchar = FALSE;
  848. X}
  849. X
  850. X#ifdef DONTINCLUDEANYMORE
  851. X/*
  852. X * NotValidFromCurschar()
  853. X *
  854. X * Mark the lines in NumLinePointers and NumLineSizes from Curschar on as
  855. X * not valid.
  856. X */
  857. X
  858. Xvoid
  859. XNotValidFromCurschar()
  860. X{
  861. X    register int    idx;
  862. X    register unsigned long num;
  863. X
  864. X    S_VALID_TO_CURSCHAR;
  865. X
  866. X    num = LINEOF(Curschar);
  867. X    for (idx = 0; idx < NumLineSizes; idx++) {
  868. X    if (LinePointers[idx]->num >= num)
  869. X        break;
  870. X    }
  871. X    NumLineSizes = idx;
  872. X}
  873. X#endif
  874. SHAR_EOF
  875. echo "extracting screen.c"
  876. sed 's/^X//' << \SHAR_EOF > screen.c
  877. X/*
  878. X * STEVIE - Simply Try this Editor for VI Enthusiasts
  879. X *
  880. X * Code Contributions By : Tim Thompson           twitch!tjt
  881. X *                         Tony Andrews           onecom!wldrdg!tony 
  882. X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  883. X */
  884. X
  885. X#include "stevie.h"
  886. X
  887. X/*
  888. X * The following variable is set (in cursupdate) to the number of physical
  889. X * lines taken by the line the cursor is on. We use this to avoid extra calls
  890. X * to plines(). The optimized routine updateline() makes sure that the size of
  891. X * the cursor line hasn't changed. If so, lines below the cursor will move up
  892. X * or down and we need to call the routine s_refresh() to examine the
  893. X * entire screen. 
  894. X */
  895. Xstatic int      Cline_size;    /* size (in rows) of the cursor line */
  896. Xstatic int      Cline_row;    /* starting row of the cursor line */
  897. X
  898. X/*
  899. X * updateline() - like s_refresh() but only for cursor line 
  900. X *
  901. X * This determines whether or not we need to call s_refresh() to examine
  902. X * the entire screen for changes. This occurs if the size of the cursor line
  903. X * (in rows) has changed.
  904. X */
  905. Xstatic void
  906. Xupdateline()
  907. X{
  908. X    char           *ptr;
  909. X    int             col;
  910. X    int             size;
  911. X    int             j;
  912. X
  913. X    if (RedrawingDisabled)    /* Is this the correct action ? */
  914. X    return;
  915. X
  916. X    ptr = format_line(Curschar->linep->s, &col);
  917. X
  918. X    size = 1 + ((col - 1) / Columns);
  919. X    if (Cline_size == size) {
  920. X    outstr(T_CI);
  921. X    windgoto(Cline_row, 0);
  922. X    if (P(P_NU)) {
  923. X        /*
  924. X         * This should be done more efficiently. 
  925. X         */
  926. X        outstr(mkline(cntllines(Filemem, Curschar)));
  927. X    }
  928. X    outstr(ptr);
  929. X
  930. X    j = col + (P(P_NU) ? 8 : 0);
  931. X    col = j % Columns;
  932. X    if ((col != 0) || (j == 0)) {
  933. X#ifdef T_END_L
  934. X        windgoto(Cline_row + size - 1, col);
  935. X        outstr(T_END_L);
  936. X#else
  937. X        for (; col < Columns; col++)
  938. X        outchar(' ');
  939. X#endif
  940. X    }
  941. X    outstr(T_CV);
  942. X    } else {
  943. X    s_refresh(VALID_TO_CURSCHAR);
  944. X    }
  945. X}
  946. X
  947. Xvoid
  948. Xcursupdate(type)
  949. X    int             type;
  950. X{
  951. X    register char   c;
  952. X    register int    incr;
  953. X    register int    i;
  954. X    register int    didincr;
  955. X
  956. X    if (MustUpdateBotchar == TRUE)
  957. X    Update_Botchar();
  958. X
  959. X    if (NumLineSizes < 0) {
  960. X    s_refresh(NOT_VALID);
  961. X    } else {
  962. X        if (LineNotValid == TRUE)
  963. X        updateline();
  964. X
  965. X    if (type != UPDATE_CURSOR) {
  966. X        s_refresh(type);
  967. X        } else if (ValidToCurschar == TRUE) {
  968. X        s_refresh(VALID_TO_CURSCHAR);
  969. X        } else if (CheckTopcharAndBotchar == TRUE) {
  970. X        s_refresh(VALID);
  971. X        }
  972. X    }
  973. X
  974. X    CheckTopcharAndBotchar = FALSE;
  975. X    MustUpdateBotchar = FALSE;
  976. X    ValidToCurschar = FALSE;
  977. X    LineNotValid = FALSE;
  978. X
  979. X    Cursrow = Curscol = Cursvcol = i = 0;
  980. X    for (i = 0; i < NumLineSizes; i++) {
  981. X    if (LinePointers[i] == Curschar->linep)
  982. X        break;
  983. X    Cursrow += LineSizes[i];
  984. X    }
  985. X
  986. X    if (P(P_NU))
  987. X    Curscol = 8;
  988. X
  989. X    Cline_row = Cursrow;
  990. X    Cline_size = LineSizes[i];
  991. X
  992. X    for (i = 0; i <= Curschar->index; i++) {
  993. X    c = Curschar->linep->s[i];
  994. X    /* A tab gets expanded, depending on the current column */
  995. X    if (c == TAB && !P(P_LS))
  996. X        incr = P(P_TS) - (Cursvcol % P(P_TS));
  997. X    else
  998. X        incr = chars[c].ch_size;
  999. X    Curscol += incr;
  1000. X    Cursvcol += incr;
  1001. X    if (Curscol >= Columns) {
  1002. X        Curscol -= Columns;
  1003. X        Cursrow++;
  1004. X        didincr = TRUE;
  1005. X    } else
  1006. X        didincr = FALSE;
  1007. X    }
  1008. X    if (didincr)
  1009. X    Cursrow--;
  1010. X
  1011. X    if (c == TAB && State == NORMAL && !P(P_LS)) {
  1012. X    Curscol--;
  1013. X    Cursvcol--;
  1014. X    } else {
  1015. X    Curscol -= incr;
  1016. X    Cursvcol -= incr;
  1017. X    }
  1018. X    if (Curscol < 0)
  1019. X    Curscol += Columns;
  1020. X
  1021. X    if (set_want_col) {
  1022. X    Curswant = Cursvcol;
  1023. X    set_want_col = FALSE;
  1024. X    }
  1025. X}
  1026. SHAR_EOF
  1027. echo "extracting search.c"
  1028. sed 's/^X//' << \SHAR_EOF > search.c
  1029. X/*
  1030. X * STEVIE - Simply Try this Editor for VI Enthusiasts
  1031. X *
  1032. X * Code Contributions By : Tim Thompson           twitch!tjt
  1033. X *                         Tony Andrews           onecom!wldrdg!tony 
  1034. X *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  1035. X */
  1036. X
  1037. X#include "stevie.h"
  1038. X/* modified Henry Spencer's regular expression routines */
  1039. X#include "regexp.h"
  1040. X
  1041. X#ifdef  MEGAMAX
  1042. Xoverlay "search"
  1043. X#endif
  1044. X
  1045. X/*
  1046. X * This file contains various searching-related routines. These fall into
  1047. X * three groups: string searches (for /, ?, n, and N), character searches
  1048. X * within a single line (for f, F, t, T, etc), and "other" kinds of searches
  1049. X * like the '%' command, and 'word' searches. 
  1050. X */
  1051. X
  1052. X/*
  1053. X * String searches 
  1054. X *
  1055. X * The actual searches are done using Henry Spencer's regular expression
  1056. X * library. 
  1057. X */
  1058. X
  1059. X#define BEGWORD "([^a-zA-Z0-9_]|^)"    /* replaces "\<" in search strings */
  1060. X#define ENDWORD "([^a-zA-Z0-9_]|$)"    /* likewise replaces "\>" */
  1061. X
  1062. Xbool_t begword;            /* does the search include a 'begin word'
  1063. X                 * match */
  1064. X
  1065. X/*
  1066. X * mapstring(s) - map special backslash sequences 
  1067. X */
  1068. Xstatic char    *
  1069. Xmapstring(s)
  1070. X    register char  *s;
  1071. X{
  1072. X    static char     ns[MAX_COLUMNS + 1];
  1073. X    register char  *p;
  1074. X
  1075. X    begword = FALSE;
  1076. X
  1077. X    for (p = ns; *s; s++) {
  1078. X    if ((*s == '(') || (*s == ')')) {
  1079. X        *p++ = '\\';
  1080. X        *p++ = *s;
  1081. X        continue;
  1082. X    }
  1083. X    if (*s != '\\') {    /* not an escape */
  1084. X        *p++ = *s;
  1085. X        continue;
  1086. X    }
  1087. X    switch (*++s) {
  1088. X      case '/':
  1089. X        *p++ = '/';
  1090. X        break;
  1091. X
  1092. X      case '<':
  1093. X        strcpy(p, BEGWORD);
  1094. X        p += strlen(BEGWORD);
  1095. X        begword = TRUE;
  1096. X        break;
  1097. X
  1098. X      case '>':
  1099. X        strcpy(p, ENDWORD);
  1100. X        p += strlen(ENDWORD);
  1101. X        break;
  1102. X
  1103. X      default:
  1104. X        *p++ = '\\';
  1105. X        *p++ = *s;
  1106. X        break;
  1107. X    }
  1108. X    }
  1109. X    *p = NUL;
  1110. X
  1111. X    return ns;
  1112. X}
  1113. X
  1114. Xstatic LPtr    *
  1115. Xbcksearch(str)
  1116. X    char           *str;
  1117. X{
  1118. X    static LPtr     infile;
  1119. X    register LPtr  *p;
  1120. X    regexp         *prog;
  1121. X    register char  *s;
  1122. X    register int    i;
  1123. X    bool_t          want_start = (*str == '^');    /* looking for start of line? */
  1124. X    register char  *match;
  1125. X
  1126. X    /* make sure str isn't empty */
  1127. X    if (str == NULL || *str == NUL)
  1128. X    return NULL;
  1129. X
  1130. X    prog = regcomp(str);
  1131. X    if (prog == NULL) {
  1132. X    emsg("Invalid search string");
  1133. X    return NULL;
  1134. X    }
  1135. X    p = Curschar;
  1136. X    dec(p);
  1137. X
  1138. X    if (begword)        /* so we don't get stuck on one match */
  1139. X    dec(p);
  1140. X
  1141. X    i = (want_start) ? 0 : p->index;
  1142. X
  1143. X    do {
  1144. X    s = p->linep->s;
  1145. X
  1146. X    if (regexec(prog, s, TRUE)) {    /* match somewhere on line */
  1147. X
  1148. X        if (want_start) {    /* could only have been one */
  1149. X        infile.linep = p->linep;
  1150. X        infile.index = (int) (prog->startp[0] - s);
  1151. X        free((char *) prog);
  1152. X        return (&infile);
  1153. X        }
  1154. X        /*
  1155. X         * Now, if there are multiple matches on this line, we have to
  1156. X         * get the last one. Or the last one before the cursor, if we're
  1157. X         * on that line. 
  1158. X         */
  1159. X
  1160. X        match = prog->startp[0];
  1161. X
  1162. X        while (regexec(prog, prog->endp[0], FALSE)) {
  1163. X        if ((i >= 0) && ((prog->startp[0] - s) > i))
  1164. X            break;
  1165. X        match = prog->startp[0];
  1166. X        }
  1167. X
  1168. X        if ((i >= 0) && ((match - s) > i)) {
  1169. X        i = -1;
  1170. X        continue;
  1171. X        }
  1172. X        infile.linep = p->linep;
  1173. X        infile.index = (int) (match - s);
  1174. X        free((char *) prog);
  1175. X        return (&infile);
  1176. X    }
  1177. X    i = -1;
  1178. X
  1179. X    } while ((p = prevline(p)) != NULL);
  1180. X
  1181. X    /*
  1182. X     * If wrapscan isn't set, bag the search now 
  1183. X     */
  1184. X    if (!P(P_WS)) {
  1185. X    free((char *) prog);
  1186. X    return NULL;
  1187. X    }
  1188. X    /* search backward from the end of the file */
  1189. X    p = prevline(Fileend);
  1190. X    do {
  1191. X    s = p->linep->s;
  1192. X
  1193. X    if (regexec(prog, s, TRUE)) {    /* match somewhere on line */
  1194. X
  1195. X        if (want_start) {    /* could only have been one */
  1196. X        infile.linep = p->linep;
  1197. X        infile.index = (int) (prog->startp[0] - s);
  1198. X        free((char *) prog);
  1199. X        return (&infile);
  1200. X        }
  1201. X        /*
  1202. X         * Now, if there are multiple matches on this line, we have to
  1203. X         * get the last one. 
  1204. X         */
  1205. X
  1206. X        match = prog->startp[0];
  1207. X
  1208. X        while (regexec(prog, prog->endp[0], FALSE))
  1209. X        match = prog->startp[0];
  1210. X
  1211. X        infile.linep = p->linep;
  1212. X        infile.index = (int) (match - s);
  1213. X        free((char *) prog);
  1214. X        return (&infile);
  1215. X    }
  1216. X    if (p->linep == Curschar->linep)
  1217. X        break;
  1218. X
  1219. X    } while ((p = prevline(p)) != NULL);
  1220. X
  1221. X    free((char *) prog);
  1222. X    return NULL;
  1223. X}
  1224. X
  1225. Xstatic LPtr    *
  1226. Xfwdsearch(str)
  1227. X    char           *str;
  1228. X{
  1229. X    static LPtr     infile;
  1230. X    LPtr           *p;
  1231. X    regexp         *prog;
  1232. X    bool_t          want_start = (*str == '^');    /* looking for start of line? */
  1233. X
  1234. X    char           *s;
  1235. X    int             i;
  1236. X
  1237. X    prog = regcomp(str);
  1238. X    if (prog == NULL) {
  1239. X    emsg("Invalid search string");
  1240. X    return NULL;
  1241. X    }
  1242. X    p = Curschar;
  1243. X    i = Curschar->index + 1;
  1244. X    do {
  1245. X    s = p->linep->s + i;
  1246. X    i = 0;
  1247. X
  1248. X    if (regexec(prog, s, i == 0)) {    /* got a match */
  1249. X        /*
  1250. X         * If we wanted the start of a line and we aren't really there,
  1251. X         * then a match doesn't count. 
  1252. X         */
  1253. X        if (want_start && (s != p->linep->s))
  1254. X        continue;
  1255. X
  1256. X        infile.linep = p->linep;
  1257. X        infile.index = (int) (prog->startp[0] - p->linep->s);
  1258. X        free((char *) prog);
  1259. X        return (&infile);
  1260. X    }
  1261. X    } while ((p = nextline(p)) != NULL);
  1262. X
  1263. X    /*
  1264. X     * If wrapscan isn't set, then don't scan from the beginning of the file.
  1265. X     * Just return failure here. 
  1266. X     */
  1267. X    if (!P(P_WS)) {
  1268. X    free((char *) prog);
  1269. X    return NULL;
  1270. X    }
  1271. X    /* search from the beginning of the file to Curschar */
  1272. X    for (p = Filemem; p != NULL; p = nextline(p)) {
  1273. X    s = p->linep->s;
  1274. X
  1275. X    if (regexec(prog, s, TRUE)) {    /* got a match */
  1276. X        infile.linep = p->linep;
  1277. X        infile.index = (int) (prog->startp[0] - s);
  1278. X        free((char *) prog);
  1279. X        return (&infile);
  1280. X    }
  1281. X    if (p->linep == Curschar->linep)
  1282. X        break;
  1283. X    }
  1284. X
  1285. X    free((char *) prog);
  1286. X    return (NULL);
  1287. X}
  1288. X
  1289. Xstatic char    *laststr = NULL;
  1290. Xstatic int      lastsdir;
  1291. X
  1292. Xstatic LPtr    *
  1293. Xssearch(dir, str)
  1294. X    int             dir;    /* FORWARD or BACKWARD */
  1295. X    char           *str;
  1296. X{
  1297. X    LPtr           *pos;
  1298. X
  1299. X    reg_ic = P(P_IC);        /* tell the regexp routines how to search */
  1300. X
  1301. X    if (laststr != str) {
  1302. X    if (laststr != NULL)
  1303. X        free(laststr);
  1304. X    laststr = strsave(str);
  1305. X    }
  1306. X    lastsdir = dir;
  1307. X
  1308. X    if (dir == BACKWARD)
  1309. X    pos = bcksearch(mapstring(str));
  1310. X    else
  1311. X    pos = fwdsearch(mapstring(str));
  1312. X
  1313. X    /*
  1314. X     * This is kind of a kludge, but its needed to make 'beginning of word'
  1315. X     * searches land on the right place. 
  1316. X     */
  1317. X    if (pos != NULL && begword) {
  1318. X    if (pos->index != 0)
  1319. X        pos->index += 1;
  1320. X    }
  1321. X    return pos;
  1322. X}
  1323. X
  1324. Xbool_t
  1325. Xdosearch(dir, str)
  1326. X    int             dir;
  1327. X    char           *str;
  1328. X{
  1329. X    LPtr           *p;
  1330. X
  1331. X    S_CHECK_TOPCHAR_AND_BOTCHAR;
  1332. X
  1333. X    if ((p = ssearch(dir, str)) == NULL) {
  1334. X    msg("Pattern not found");
  1335. X    return (FALSE);
  1336. X    } else {
  1337. X    LPtr            savep;
  1338. X
  1339. X    /* if we're backing up, we make sure the line we're on */
  1340. X    /* is on the screen. */
  1341. X    setpcmark();
  1342. X    *Curschar = savep = *p;
  1343. X
  1344. X    return (TRUE);
  1345. X    }
  1346. X}
  1347. X
  1348. Xvoid
  1349. Xsearchagain(dir)
  1350. X    int             dir;
  1351. X{
  1352. X    if (laststr == NULL)
  1353. X    beep();
  1354. X    else
  1355. X    dosearch(dir, laststr);
  1356. X
  1357. X    lastsdir = dir;
  1358. X}
  1359. X
  1360. X#define OTHERDIR(x)     (((x) == FORWARD) ? BACKWARD : FORWARD)
  1361. X
  1362. Xbool_t
  1363. Xrepsearch(flag)
  1364. X    bool_t          flag;
  1365. X{
  1366. X    int             dir = lastsdir;
  1367. X    bool_t          found;
  1368. X
  1369. X    if (laststr == NULL) {
  1370. X    beep();
  1371. X    return FALSE;
  1372. X    }
  1373. X    found = dosearch(flag ? OTHERDIR(lastsdir) : lastsdir, laststr);
  1374. X
  1375. X    /*
  1376. X     * We have to save and restore 'lastsdir' because it gets munged by
  1377. X     * ssearch() and winds up saving the wrong direction from here if 'flag'
  1378. X     * is true. 
  1379. X     */
  1380. X    lastsdir = dir;
  1381. X
  1382. X    return (found);
  1383. X}
  1384. X
  1385. X/*
  1386. X * regerror - called by regexp routines when errors are detected. 
  1387. X */
  1388. Xvoid
  1389. Xregerror(s)
  1390. X    char           *s;
  1391. X{
  1392. X    emsg(s);
  1393. X}
  1394. X
  1395. X/*
  1396. X * dosub(lp, up, cmd)
  1397. X *
  1398. X * Perform a substitution from line 'lp' to line 'up' using the
  1399. X * command pointed to by 'cmd' which should be of the form:
  1400. X *
  1401. X * /pattern/substitution/g
  1402. X *
  1403. X * The trailing 'g' is optional and, if present, indicates that multiple
  1404. X * substitutions should be performed on each line, if applicable.
  1405. X * The usual escapes are supported as described in the regexp docs.
  1406. X */
  1407. X
  1408. Xvoid
  1409. Xdosub(lp, up, cmd)
  1410. X    LPtr           *lp, *up;
  1411. X    char           *cmd;
  1412. X{
  1413. X    LINE           *cp;
  1414. X    char           *pat, *sub;
  1415. X    regexp         *prog;
  1416. X    int             nsubs;
  1417. X    bool_t          do_all;    /* do multiple substitutions per line */
  1418. X    int             n;
  1419. X
  1420. X    /*
  1421. X     * If no range was given, do the current line. If only one line was
  1422. X     * given, just do that one. 
  1423. X     */
  1424. X    if (lp->linep == NULL)
  1425. X    *up = *lp = *Curschar;
  1426. X    else {
  1427. X    if (up->linep == NULL)
  1428. X        *up = *lp;
  1429. X    }
  1430. X
  1431. X    pat = ++cmd;        /* skip the initial '/' */
  1432. X
  1433. X    while (*cmd) {
  1434. X    if (cmd[0] == '/' && cmd[-1] != '\\') {
  1435. X        *cmd++ = NUL;
  1436. X        break;
  1437. X    }
  1438. X    cmd++;
  1439. X    }
  1440. X
  1441. X    if (*pat == NUL) {
  1442. X    emsg("NULL pattern specified");
  1443. X    return;
  1444. X    }
  1445. X    sub = cmd;
  1446. X
  1447. X    do_all = FALSE;
  1448. X
  1449. X    while (*cmd) {
  1450. X    if (cmd[0] == '/' && cmd[-1] != '\\') {
  1451. X        do_all = (cmd[1] == 'g');
  1452. X        *cmd = NUL;
  1453. X        break;
  1454. X    }
  1455. X    cmd++;
  1456. X    }
  1457. X
  1458. X    reg_ic = P(P_IC);        /* set "ignore case" flag appropriately */
  1459. X
  1460. X    prog = regcomp(pat);
  1461. X    if (prog == NULL) {
  1462. X    emsg("Invalid search string");
  1463. X    return;
  1464. X    }
  1465. X    nsubs = 0;
  1466. X
  1467. X    ResetBuffers();
  1468. X    n = RowNumber(lp);
  1469. X
  1470. X    cp = lp->linep;
  1471. X    for (; cp != Fileend->linep && cp != NULL; cp = cp->next, n++) {
  1472. X    if (regexec(prog, cp->s, TRUE)) {    /* a match on this line */
  1473. X        char           *ns, *sns, *p;
  1474. X
  1475. X        /*
  1476. X         * Save the line that was last changed for the final cursor
  1477. X         * position (just like the real vi). 
  1478. X         */
  1479. X        Curschar->linep = cp;
  1480. X
  1481. X        /*
  1482. X         * Get some space for a temporary buffer to do the substitution
  1483. X         * into. 
  1484. X         */
  1485. X        sns = ns = alloc(2048);
  1486. X        if (ns == NULL)
  1487. X        break;
  1488. X
  1489. X        *sns = NUL;
  1490. X
  1491. X        p = cp->s;
  1492. X
  1493. X        do {
  1494. X        for (ns = sns; *ns; ns++);
  1495. X        /*
  1496. X         * copy up to the part that matched 
  1497. X         */
  1498. X        while (p < prog->startp[0])
  1499. X            *ns++ = *p++;
  1500. X
  1501. X        regsub(prog, sub, ns);
  1502. X
  1503. X        /*
  1504. X         * continue searching after the match 
  1505. X         */
  1506. X        p = prog->endp[0];
  1507. X
  1508. X        } while (regexec(prog, p, FALSE) && do_all);
  1509. X
  1510. X        for (ns = sns; *ns; ns++);
  1511. X
  1512. X        /*
  1513. X         * copy the rest of the line, that didn't match 
  1514. X         */
  1515. X        while (*p)
  1516. X        *ns++ = *p++;
  1517. X
  1518. X        *ns = NUL;
  1519. X
  1520. X        AppendPositionToUndoUndobuff(0, n);
  1521. X        AppendPositionToUndobuff(0, n);
  1522. X        AppendToUndoUndobuff("c$");
  1523. X        AppendToUndobuff("c$");
  1524. X        AppendToUndoUndobuff(sns);
  1525. X        AppendToUndobuff(cp->s);
  1526. X        AppendToUndoUndobuff(ESC_STR);
  1527. X        AppendToUndobuff(ESC_STR);
  1528. X
  1529. X        free(cp->s);    /* free the original line */
  1530. X        cp->s = strsave(sns);    /* and save the modified str */
  1531. X        cp->size = strlen(cp->s) + 1;
  1532. X        free(sns);        /* free the temp buffer */
  1533. X        nsubs++;
  1534. X    }
  1535. X    if (cp == up->linep)
  1536. X        break;
  1537. X    }
  1538. X
  1539. X    if (nsubs) {
  1540. X    CHANGED;
  1541. X    S_NOT_VALID;
  1542. X    AppendPositionToUndoUndobuff(0, 1);
  1543. X    AppendPositionToUndobuff(0, 1);
  1544. X    beginline(TRUE);
  1545. X    if (nsubs >= P(P_RP))
  1546. X        smsg("%d substitution%c", nsubs, (nsubs > 1) ? 's' : ' ');
  1547. X    } else
  1548. X    msg("No match");
  1549. X
  1550. X    free((char *) prog);
  1551. X}
  1552. X
  1553. X/*
  1554. X * doglob(cmd)
  1555. X *
  1556. X * Execute a global command of the form:
  1557. X *
  1558. X * g/pattern/X
  1559. X *
  1560. X * where 'x' is a command character, currently one of the following:
  1561. X *
  1562. X * d    Delete all matching lines
  1563. X * p    Print all matching lines
  1564. X *
  1565. X * The command character (as well as the trailing slash) is optional, and
  1566. X * is assumed to be 'p' if missing.
  1567. X */
  1568. X
  1569. Xvoid
  1570. Xdoglob(lp, up, cmd)
  1571. X    LPtr           *lp, *up;
  1572. X    char           *cmd;
  1573. X{
  1574. X    LINE           *cp;
  1575. X
  1576. X    char           *pat;
  1577. X    regexp         *prog;
  1578. X    int             ndone;
  1579. X    char            cmdchar = NUL;    /* what to do with matching lines */
  1580. X    int             nu;
  1581. X    int             nuu = 0;
  1582. X
  1583. X    /*
  1584. X     * If no range was given, do every line. If only one line was given, just
  1585. X     * do that one. 
  1586. X     */
  1587. X    if (lp->linep == NULL) {
  1588. X    *lp = *Filemem;
  1589. X    *up = *Fileend;
  1590. X    } else {
  1591. X    if (up->linep == NULL)
  1592. X        *up = *lp;
  1593. X    }
  1594. X
  1595. X    pat = ++cmd;        /* skip the initial '/' */
  1596. X
  1597. X    while (*cmd) {
  1598. X    if (cmd[0] == '/' && cmd[-1] != '\\') {
  1599. X        cmdchar = cmd[1];
  1600. X        *cmd = NUL;
  1601. X        break;
  1602. X    }
  1603. X    cmd++;
  1604. X    }
  1605. X    if (cmdchar == NUL)
  1606. X    cmdchar = 'p';
  1607. X
  1608. X    reg_ic = P(P_IC);        /* set "ignore case" flag appropriately */
  1609. X
  1610. X    if (cmdchar != 'd' && cmdchar != 'p') {
  1611. X    emsg("Invalid command character");
  1612. X    return;
  1613. X    }
  1614. X    prog = regcomp(pat);
  1615. X    if (prog == NULL) {
  1616. X    emsg("Invalid search string");
  1617. X    return;
  1618. X    }
  1619. X    msg("");
  1620. X    ndone = 0;
  1621. X
  1622. X    nu = RowNumber(lp);
  1623. X    if (cmdchar == 'd') {
  1624. X    ResetBuffers();
  1625. X    nuu = nu;
  1626. X    }
  1627. X    cp = lp->linep;
  1628. X    for (; cp != Fileend->linep && cp != NULL; cp = cp->next, nu++) {
  1629. X    if (regexec(prog, cp->s, TRUE)) {    /* a match on this line */
  1630. X        Curschar->linep = cp;
  1631. X        Curschar->index = 0;
  1632. X
  1633. X        switch (cmdchar) {
  1634. X
  1635. X          case 'd':    /* delete the line */
  1636. X        AppendPositionToUndoUndobuff(0, nuu);
  1637. X        AppendToUndoUndobuff("dd");
  1638. X        if (buf1line() && (ndone == 0)) {
  1639. X            AppendToUndobuff("a");
  1640. X        } else if (buf1line()) {
  1641. X            AppendToUndobuff("j");
  1642. X            AppendToUndobuff("I");
  1643. X        } else if (cp->next == Fileend->linep) {
  1644. X            AppendPositionToUndobuff(0, nu);
  1645. X            AppendToUndobuff("o");
  1646. X        } else {
  1647. X            AppendPositionToUndobuff(0, nu);
  1648. X            AppendToUndobuff("O");
  1649. X        }
  1650. X        AppendToUndobuff(cp->s);
  1651. X        AppendToUndobuff(ESC_STR);
  1652. X
  1653. X        delline(1);
  1654. X        break;
  1655. X
  1656. X          case 'p':    /* print the line */
  1657. X        if (P(P_NU)) {
  1658. X            outstr(mkline(nu));
  1659. X        }
  1660. X        outstr(T_CV);
  1661. X        outstr(format_line(cp->s, (int *) NULL));
  1662. X        outstr(T_CI);
  1663. X        outstr("\r\n");
  1664. X        break;
  1665. X        }
  1666. X        ndone++;
  1667. X    } else if (cmdchar == 'd') {
  1668. X        nuu++;
  1669. X    }
  1670. X    if (cp == up->linep)
  1671. X        break;
  1672. X    }
  1673. X
  1674. X    if (ndone) {
  1675. X    switch (cmdchar) {
  1676. X
  1677. X      case 'd':
  1678. X        S_NOT_VALID;
  1679. X        AppendPositionToUndobuff(0, 1);
  1680. X        if (ndone >= P(P_RP))
  1681. X        smsg("%d fewer line%c", ndone,
  1682. X             (ndone > 1) ? 's' : ' ');
  1683. X        break;
  1684. X
  1685. X      case 'p':
  1686. X        wait_return();
  1687. X        break;
  1688. X    }
  1689. X    stuffReadbuff("^");
  1690. X    } else
  1691. X    msg("No match");
  1692. X
  1693. X    free((char *) prog);
  1694. X}
  1695. X
  1696. X/*
  1697. X * Character Searches 
  1698. X */
  1699. X
  1700. Xstatic char     lastc = NUL;    /* last character searched for */
  1701. Xstatic int      lastcdir;    /* last direction of character search */
  1702. Xstatic int      lastctype;    /* last type of search ("find" or "to") */
  1703. X
  1704. X/*
  1705. X * searchc(c, dir, type) 
  1706. X *
  1707. X * Search for character 'c', in direction 'dir'. If type is 0, move to the
  1708. X * position of the character, otherwise move to just before the char. 
  1709. X */
  1710. Xbool_t
  1711. Xsearchc(c, dir, type)
  1712. X    char            c;
  1713. X    int             dir;
  1714. X    int             type;
  1715. X{
  1716. X    LPtr            save;
  1717. X
  1718. X    save = *Curschar;        /* save position in case we fail */
  1719. X    lastc = c;
  1720. X    lastcdir = dir;
  1721. X    lastctype = type;
  1722. X
  1723. X    /*
  1724. X     * On 'to' searches, skip one to start with so we can repeat searches in
  1725. X     * the same direction and have it work right. 
  1726. X     */
  1727. X    if (type)
  1728. X    (dir == FORWARD) ? oneright() : oneleft();
  1729. X
  1730. X    while ((dir == FORWARD) ? oneright() : oneleft()) {
  1731. X    if (gchar(Curschar) == c) {
  1732. X        if (type)
  1733. X        (dir == FORWARD) ? oneleft() : oneright();
  1734. X        return TRUE;
  1735. X    }
  1736. X    }
  1737. X    *Curschar = save;
  1738. X    return FALSE;
  1739. X}
  1740. X
  1741. Xbool_t
  1742. Xcrepsearch(flag)
  1743. X    int             flag;
  1744. X{
  1745. X    int             dir = lastcdir;
  1746. X    int             rval;
  1747. X
  1748. X    if (lastc == NUL)
  1749. X    return FALSE;
  1750. X
  1751. X    rval = searchc(lastc, flag ? OTHERDIR(lastcdir) : lastcdir, lastctype);
  1752. X
  1753. X    lastcdir = dir;        /* restore dir., since it may have changed */
  1754. X
  1755. X    return rval;
  1756. X}
  1757. X
  1758. X/*
  1759. X * "Other" Searches 
  1760. X */
  1761. X
  1762. X/*
  1763. X * showmatch - move the cursor to the matching paren or brace 
  1764. X */
  1765. XLPtr           *
  1766. Xshowmatch()
  1767. X{
  1768. X    static LPtr     pos;
  1769. X    int             (*move) (), inc(), dec();
  1770. X    char            initc = gchar(Curschar);    /* initial char */
  1771. X    char            findc;    /* terminating char */
  1772. X    char            c;
  1773. X    int             count = 0;
  1774. X
  1775. X    pos = *Curschar;        /* set starting point */
  1776. X
  1777. X    switch (initc) {
  1778. X
  1779. X      case '(':
  1780. X    findc = ')';
  1781. X    move = inc;
  1782. X    break;
  1783. X      case ')':
  1784. X    findc = '(';
  1785. X    move = dec;
  1786. X    break;
  1787. X      case '{':
  1788. X    findc = '}';
  1789. X    move = inc;
  1790. X    break;
  1791. X      case '}':
  1792. X    findc = '{';
  1793. X    move = dec;
  1794. X    break;
  1795. X      case '[':
  1796. X    findc = ']';
  1797. X    move = inc;
  1798. X    break;
  1799. X      case ']':
  1800. X    findc = '[';
  1801. X    move = dec;
  1802. X    break;
  1803. X      default:
  1804. X    return (LPtr *) NULL;
  1805. X    }
  1806. X
  1807. X    while ((*move) (&pos) != -1) {    /* until end of file */
  1808. X    c = gchar(&pos);
  1809. X    if (c == initc)
  1810. X        count++;
  1811. X    else if (c == findc) {
  1812. X        if (count == 0)
  1813. X        return &pos;
  1814. X        count--;
  1815. X    }
  1816. X    }
  1817. X    return (LPtr *) NULL;    /* never found it */
  1818. X}
  1819. X
  1820. X/*
  1821. X * findfunc(dir) - Find the next function in direction 'dir' 
  1822. X *
  1823. X * Return TRUE if a function was found. 
  1824. X */
  1825. Xbool_t
  1826. Xfindfunc(dir)
  1827. X    int             dir;
  1828. X{
  1829. X    LPtr           *curr;
  1830. X
  1831. X    S_CHECK_TOPCHAR_AND_BOTCHAR;
  1832. X
  1833. X    curr = Curschar;
  1834. X
  1835. X    do {
  1836. X    curr = (dir == FORWARD) ? nextline(curr) : prevline(curr);
  1837. X
  1838. X    if (curr != NULL && curr->linep->s[0] == '{') {
  1839. X        setpcmark();
  1840. X        *Curschar = *curr;
  1841. X        return TRUE;
  1842. X    }
  1843. X    } while (curr != NULL);
  1844. X
  1845. X    return FALSE;
  1846. X}
  1847. X
  1848. X/*
  1849. X * The following routines do the word searches performed by the 'w', 'W',
  1850. X * 'b', 'B', 'e', and 'E' commands. 
  1851. X */
  1852. X
  1853. X/*
  1854. X * To perform these searches, characters are placed into one of three
  1855. X * classes, and transitions between classes determine word boundaries. 
  1856. X *
  1857. X * The classes are: 
  1858. X *
  1859. X * 0 - white space 1 - letters, digits, and underscore 2 - everything else 
  1860. X */
  1861. X
  1862. Xstatic int      stype;        /* type of the word motion being performed */
  1863. X
  1864. X#define C0(c)   (((c) == ' ') || ((c) == '\t') || ((c) == NUL))
  1865. X#define C1(c)   (isalpha(c) || isdigit(c) || ((c) == '_'))
  1866. X
  1867. X/*
  1868. X * cls(c) - returns the class of character 'c' 
  1869. X *
  1870. X * The 'type' of the current search modifies the classes of characters if a 'W',
  1871. X * 'B', or 'E' motion is being done. In this case, chars. from class 2 are
  1872. X * reported as class 1 since only white space boundaries are of interest. 
  1873. X */
  1874. Xstatic int
  1875. Xcls(c)
  1876. X    char            c;
  1877. X{
  1878. X    if (C0(c))
  1879. X    return 0;
  1880. X
  1881. X    if (C1(c))
  1882. X    return 1;
  1883. X
  1884. X    /*
  1885. X     * If stype is non-zero, report these as class 1. 
  1886. X     */
  1887. X    return (stype == 0) ? 2 : 1;
  1888. X}
  1889. X
  1890. X
  1891. X/*
  1892. X * fwd_word(pos, type) - move forward one word 
  1893. X *
  1894. X * Returns the resulting position, or NULL if EOF was reached. 
  1895. X */
  1896. XLPtr           *
  1897. Xfwd_word(p, type)
  1898. X    LPtr           *p;
  1899. X    int             type;
  1900. X{
  1901. X    static LPtr     pos;
  1902. X    int             sclass = cls(gchar(p));    /* starting class */
  1903. X
  1904. X    S_CHECK_TOPCHAR_AND_BOTCHAR;
  1905. X
  1906. X    pos = *p;
  1907. X
  1908. X    stype = type;
  1909. X
  1910. X    /*
  1911. X     * We always move at least one character. 
  1912. X     */
  1913. X    if (inc(&pos) == -1)
  1914. X    return NULL;
  1915. X
  1916. X    if (sclass != 0) {
  1917. X    while (cls(gchar(&pos)) == sclass) {
  1918. X        if (inc(&pos) == -1)
  1919. X        return NULL;
  1920. X    }
  1921. X    /*
  1922. X     * If we went from 1 -> 2 or 2 -> 1, return here. 
  1923. X     */
  1924. X    if (cls(gchar(&pos)) != 0)
  1925. X        return &pos;
  1926. X    }
  1927. X    /* We're in white space; go to next non-white */
  1928. X
  1929. X    while (cls(gchar(&pos)) == 0) {
  1930. X    /*
  1931. X     * We'll stop if we land on a blank line 
  1932. X     */
  1933. X    if (pos.index == 0 && pos.linep->s[0] == NUL)
  1934. X        break;
  1935. X
  1936. X    if (inc(&pos) == -1)
  1937. X        return NULL;
  1938. X    }
  1939. X
  1940. X    return &pos;
  1941. X}
  1942. X
  1943. X/*
  1944. X * bck_word(pos, type) - move backward one word 
  1945. X *
  1946. X * Returns the resulting position, or NULL if top-of-file was reached. 
  1947. X */
  1948. XLPtr           *
  1949. Xbck_word(p, type)
  1950. X    LPtr           *p;
  1951. X    int             type;
  1952. X{
  1953. X    static LPtr     pos;
  1954. X    int             sclass = cls(gchar(p));    /* starting class */
  1955. X
  1956. X    S_CHECK_TOPCHAR_AND_BOTCHAR;
  1957. X
  1958. X    pos = *p;
  1959. X
  1960. X    stype = type;
  1961. X
  1962. X    if (dec(&pos) == -1)
  1963. X    return NULL;
  1964. X
  1965. X    /*
  1966. X     * If we're in the middle of a word, we just have to back up to the start
  1967. X     * of it. 
  1968. X     */
  1969. X    if (cls(gchar(&pos)) == sclass && sclass != 0) {
  1970. X    /*
  1971. X     * Move backward to start of the current word 
  1972. X     */
  1973. X    while (cls(gchar(&pos)) == sclass) {
  1974. X        if (dec(&pos) == -1)
  1975. X        return NULL;
  1976. X    }
  1977. X    inc(&pos);        /* overshot - forward one */
  1978. X    return &pos;
  1979. X    }
  1980. X    /*
  1981. X     * We were at the start of a word. Go back to the start of the prior
  1982. X     * word. 
  1983. X     */
  1984. X
  1985. X    while (cls(gchar(&pos)) == 0) {    /* skip any white space */
  1986. X    /*
  1987. X     * We'll stop if we land on a blank line 
  1988. X     */
  1989. X    if (pos.index == 0 && pos.linep->s[0] == NUL)
  1990. X        return &pos;
  1991. X
  1992. X    if (dec(&pos) == -1)
  1993. X        return NULL;
  1994. X    }
  1995. X
  1996. X    sclass = cls(gchar(&pos));
  1997. X
  1998. X    /*
  1999. X     * Move backward to start of this word. 
  2000. X     */
  2001. X    while (cls(gchar(&pos)) == sclass) {
  2002. X    if (dec(&pos) == -1)
  2003. X        return NULL;
  2004. X    }
  2005. X    inc(&pos);            /* overshot - forward one */
  2006. X
  2007. X    return &pos;
  2008. X}
  2009. X
  2010. X/*
  2011. X * end_word(pos, type) - move to the end of the word 
  2012. X *
  2013. X * There is an apparent bug in the 'e' motion of the real vi. At least on the
  2014. X * System V Release 3 version for the 80386. Unlike 'b' and 'w', the 'e'
  2015. X * motion crosses blank lines. When the real vi crosses a blank line in an
  2016. X * 'e' motion, the cursor is placed on the FIRST character of the next
  2017. X * non-blank line. The 'E' command, however, works correctly. Since this
  2018. X * appears to be a bug, I have not duplicated it here. 
  2019. X *
  2020. X * Returns the resulting position, or NULL if EOF was reached. 
  2021. X */
  2022. XLPtr           *
  2023. Xend_word(p, type)
  2024. X    LPtr           *p;
  2025. X    int             type;
  2026. X{
  2027. X    static LPtr     pos;
  2028. X    int             sclass = cls(gchar(p));    /* starting class */
  2029. X
  2030. X    S_CHECK_TOPCHAR_AND_BOTCHAR;
  2031. X
  2032. X    pos = *p;
  2033. X
  2034. X    stype = type;
  2035. X
  2036. X    if (inc(&pos) == -1)
  2037. X    return NULL;
  2038. X
  2039. X    /*
  2040. X     * If we're in the middle of a word, we just have to move to the end of
  2041. X     * it. 
  2042. X     */
  2043. X    if (cls(gchar(&pos)) == sclass && sclass != 0) {
  2044. X    /*
  2045. X     * Move forward to end of the current word 
  2046. X     */
  2047. X    while (cls(gchar(&pos)) == sclass) {
  2048. X        if (inc(&pos) == -1)
  2049. X        return NULL;
  2050. X    }
  2051. X    dec(&pos);        /* overshot - forward one */
  2052. X    return &pos;
  2053. X    }
  2054. X    /*
  2055. X     * We were at the end of a word. Go to the end of the next word. 
  2056. X     */
  2057. X
  2058. X    while (cls(gchar(&pos)) == 0) {    /* skip any white space */
  2059. X    if (inc(&pos) == -1)
  2060. X        return NULL;
  2061. X    }
  2062. X
  2063. X    sclass = cls(gchar(&pos));
  2064. X
  2065. X    /*
  2066. X     * Move forward to end of this word. 
  2067. X     */
  2068. X    while (cls(gchar(&pos)) == sclass) {
  2069. X    if (inc(&pos) == -1)
  2070. X        return NULL;
  2071. X    }
  2072. X    dec(&pos);            /* overshot - forward one */
  2073. X
  2074. X    return &pos;
  2075. X}
  2076. SHAR_EOF
  2077. echo "End of archive 5 (of 6)"
  2078. # if you want to concatenate archives, remove anything after this line
  2079. exit
  2080.